import random
from typing import Dict, Any, List

import numpy as np

import re
from typing import Optional, Union, Sequence

import json

from agentscope.message import Msg
from agentscope.agents import AgentBase
from agentscope.models import ModelResponse
from agentscope.parsers import MarkdownJsonDictParser

DIA_LEN=3
class conclusionAgent(AgentBase):
    parser = MarkdownJsonDictParser(
        content_hint='{"conclusion": "你总结的记忆..."}',
        required_keys=["conclusion"],
    )

    def __init__(self,
                 name: str,
                 model_config_name: str,
                 sys_prompt="",
                 ) -> None:
        super().__init__(
            name=name,
            sys_prompt=sys_prompt,
            model_config_name=model_config_name,
        )
        """
                初始化一个智能体（Agent）

                :param agent_id: 智能体的唯一标识符
                """
        # self.sys_prompt=self.generate_basic_prompt(pro)
        self.name = name

    def generate_narrative_memory_prompt(self, long_term: str, msg_list: list) -> str:
        return f"""
    # 社会认知记忆编织器（对话体版）

---输入开始---
    ■■■以下为记忆输入■■■
    【记忆输入】 
    "曾经的一段记忆" → 
    {long_term if len(long_term)>=3 else "暂无系统化记忆"}

    【对话输入】 
    最近三次关键交互 → 
    {self.format_msg_dialogues(msg_list) if len(msg_list) >= DIA_LEN else '※ 对话不足三次暂不形成新记忆锚点'}
---输入结束---

    ---输出规则---
1. **认知脉络梳理**
   - 识别立场演变模式：从"始终认为..."到"开始质疑..."的转变轨迹
   - 标注重大认知转折点：当新信息动摇原有信念的关键时刻

2. **社会关系重估**
   - 重建对话者画像：根据发言模式推断性格特质（如激进/保守）
   - 绘制群体立场地图：识别主流意见与少数派声音

3. **叙事重构机制**
   - 选择性强化：突出支持当前认知框架的对话片段
   - 合理化修正：为矛盾记忆构建逻辑衔接（如"当时没意识到..."）
   - 象征性转化：将复杂争议转化为隐喻叙事（如"如同棋盘上的对弈"）

    ---输出规范---
「记忆叙事结构」：
[情感基调] ← 主要情绪与次要情绪的组合
[认知特征] ← 演变/固守/矛盾/突破的状态标注
[记忆文本] ← 480-520字自白体，必须包含：
   - 1个历史认知参照点
   - 2种群体立场镜像
   - 3层观点演进脉络

    ■■■ 输出示例 ■■■
    [遗憾/反思] [演变中/矛盾态]
    当'A'再次用那种不容置疑的语气强调'沉默等同默许'时，半年前社区公告栏上被撕毁的联名信突然浮现在意识表层。
    曾经深信不疑的民主辩论理想，在目睹邻里关系因立场对立而冰冻后，开始理解'B'所说的弹性空间或许包含着更深层的智慧。
    就像图书馆里那些被反复批注的争议著作，越是鲜明的立场越容易在时间推移中显露裂痕。
    现在更倾向于在表达观点时保留修正余地——当'A'激烈抨击妥协行为时，我注意到三位长期沉默的成员悄悄退出了群聊。或许真正的共识，产生于留白的艺术而非交锋的力度之间。
    """

    def format_msg_dialogues(self, msg_list: list) -> str:
        return "\n".join([f"{msg.name}（{msg.role}）：{msg.content}" for msg in msg_list[-3:]])

    def conclusion(self, long_term: str, msg_list: list) -> str:
        print("正在总结------------\n")
        prompt_str = self.sys_prompt#为空

        prompt_str += self.generate_narrative_memory_prompt(long_term, msg_list)

        prompt_str += self.parser.format_instruction

        sys_msg_hint = Msg("system", prompt_str, role="system")  # 这个会变成response的prompt但不会写入到system

        prompt = self.model.format(  # 一个合并de动作
            sys_msg_hint,  # 背景prompt
            #self.memory.get_memory()  # 返回的list是一个受保护类型的msg列表
        )  # TODO 这个正好完美适配我的想法
        print(prompt)
        response = None
        try:
            response = self.get_response_with_retries(prompt)
        except Exception as final_error:
            print("所有尝试均失败。错误信息:", final_error)

        self.speak(
            Msg(
                self.name,
                response,  # 这里如果生成的是json可以用json.dump
                role="assistant",
            ),
        )

        if self.memory:  # 启用记忆模块就加进来把自己说的历史输出
            self.memory.add(Msg(self.name, response, role="system"))
        # TODO 遗忘机制

        # Hide thought from the response
        return response#TODO 转成str

    def get_response_with_retries(self, prompt, max_retries=5):
        """
        尝试调用 self.model 并获取 .raw 属性。如果发生错误，则重试，直到达到最大重试次数。

        :param prompt: 提示内容
        :param parse_func: 解析函数
        :param max_retries: 最大重试次数（默认3次）
        :return: response.raw
        :raises: 最后一次尝试时抛出的异常
        """
        attempt = 0
        while attempt < max_retries:
            try:
                response = self.model(
                    prompt
                )
                parsed_response = self.parser.parse(response)
                return parsed_response.parsed  # 成功，返回结果
            except Exception as e:
                attempt += 1
                print(f"尝试第 {attempt} 次失败。错误信息: {e}")
                if attempt == max_retries:
                    print("达到最大重试次数，抛出异常。")
                    raise  # 达到最大重试次数，重新抛出异常
                else:
                    print("正在重试...")

    def __repr__(self):
        """
        打印智能体的基本信息
        """
        return (f"Agent(ID={self.id}, Name={self.profile['name']}, "
                f"Belief={self.belief:.2f}, Neighbors={len(self.neighbors)})")
